#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/times.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>

// this is *very* expensive - I need to figure out how to cut it down
unsigned long get_cpu_idle_ticks_slow(int cid, int do_it) {
  FILE* pfile = NULL;
  char* pfile_name = "/proc/stat"; 
  if ((pfile = fopen(pfile_name, "r")) == NULL) {
    printf("fopen /proc/stat: %s\n", strerror(errno));
  }
  int i;
  int cpu;
  unsigned long utime, nice, stime, idle = 0, iowait, irq, softirq, steal, guest; 

  if (do_it) {
    char line[500];
    for (i = 0; i <= cid; i++) {
      if (fgets(line, 499, pfile) == NULL) {
        printf("fgets on %s: %s", pfile_name, strerror(errno));
        exit(-1);
      }
    }
    if (fscanf(pfile, "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu\n", 
               &cpu, &utime, &nice, &stime, &idle, &iowait, &irq, 
               &softirq, &steal, &guest) == EOF) {
      printf("fscanf on %s: %s", pfile_name, strerror(errno));
      exit(-1);
    }
  }
  fclose(pfile);
  return idle;
}

long long get_cpu_idle_ticks(int cid) {
  FILE* pfile = NULL;
  char pfile_name[255];
  sprintf(pfile_name, "/proc/per_cpu_stats/cpu%d", cid);
  //  printf("pfile_name = %s\n", pfile_name);
  if ((pfile = fopen(pfile_name, "r")) == NULL) {
    printf("fopen %s: %s\n", pfile_name, strerror(errno));
    exit(-1);
  }
  long long idle;
  char buff[101];
  if (fgets(buff, 100, pfile) == NULL) {
  //  if (fscanf(pfile, "llu", &idle) == EOF) {
    printf("fscanf on %s: %s\n", pfile_name, strerror(errno));
    exit(-1);
  }
  fclose(pfile);
  idle = atoll(buff);
  //  printf("scanned = %s\n", buff);
  return idle;
}

double get_current_time() {
	static double starting_time = -1;
  struct timespec ts;
  syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
  double clock_time = (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9; 
  if (starting_time == -1) starting_time = clock_time;
  return clock_time - starting_time;
}


int main(int argc, char** argv) {
  int i;
  double t = get_current_time();
  int cid = atoi(argv[1]);
  //  unsigned long start_ticks = get_cpu_idle_ticks_slow(cid, 1), ticks;
  unsigned long long start_ticks = get_cpu_idle_ticks(cid), ticks;
  printf("start ticks %llu\n", start_ticks);
  for (i = 0; i < 500; i++) {
    //    ticks = get_cpu_idle_ticks_slow(cid, 1);
    ticks = get_cpu_idle_ticks(cid);
    int j;
    for (j = 0; j < 100000; j++) {
      double x = ticks;
      double y = (double)(cid + 1) * (double)x * (i + 1) / (j + 1);
      if (x == 0) x = 0.5;
      if (x + y / (double)j == 0) printf("is zero");
    }
  }
  sleep(1);
  //  ticks = get_cpu_idle_ticks_slow(cid, 1);
  ticks = get_cpu_idle_ticks(cid);
  printf("elapsed time %.3f, idle %.3fs, ticks idle %llu\n", get_current_time() - t, 
         (ticks - start_ticks) / (double)sysconf(_SC_CLK_TCK), ticks);
  return 0;
}
    
